package net.luohuasheng.bee.proxy.core.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.luohuasheng.bee.proxy.core.exception.JsonException;

import java.io.IOException;

public class JsonUtils {
    /**
     * 忽略对象中值为NULL或""的属性
     */
    public static final JsonUtils EXCLUDE_EMPTY = new JsonUtils(JsonInclude.Include.NON_EMPTY);

    /**
     * 忽略对象中值为默认值的属性
     */
    public static final JsonUtils EXCLUDE_DEFAULT = new JsonUtils(JsonInclude.Include.NON_DEFAULT);

    /**
     * 默认不排除任何属性
     */
    public static final JsonUtils DEFAULT = new JsonUtils();

    private ObjectMapper mapper;

    private JsonUtils() {
        mapper = new ObjectMapper();
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    private JsonUtils(JsonInclude.Include include) {
        mapper = new ObjectMapper();
        mapper.setSerializationInclusion(include);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    }

    public ObjectMapper mapper() {
        return mapper;
    }


    public String toJson(Object target) {
        try {
            return mapper.writeValueAsString(target);
        } catch (IOException e) {
            throw new JsonException(e);
        }
    }


    public <T> T fromJson(String json, Class<T> target) {
        if (json == null) {
            return null;
        }
        try {
            return mapper.readValue(json, target);
        } catch (IOException e) {
            throw new JsonException(e);
        }
    }


    public <T> T fromJson(String json, JavaType javaType) {
        if (json == null) {
            return null;
        }
        try {
            return CastUtils.cast(mapper.readValue(json, javaType));
        } catch (Exception e) {
            throw new JsonException(e);
        }
    }


    public JavaType createCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }



}
